
#include "system_config.h"

// PIC32 configuration bits
#if defined(__32MX270F256B__)
    // Oscillator
    #pragma config FNOSC    = PRIPLL        // Oscillator Selection
    #pragma config POSCMOD  = EC            // Primary Oscillator
    #pragma config OSCIOFNC = OFF           // CLKO Enable
    // 8 Mhz
    #pragma config UPLLIDIV = DIV_2         // USB PLL Input Divider
    #pragma config FPLLIDIV = DIV_2         // PLL Input Divider
    // Other
    #pragma config UPLLEN   = ON            // USB PLL Enabled
    #pragma config FPLLMUL  = MUL_20        // PLL Multiplier
    #pragma config FPLLODIV = DIV_2         // PLL Output Divider
    #pragma config FPBDIV   = DIV_1         // Peripheral Clock divisor
    #pragma config FWDTEN   = OFF           // Watchdog Timer
    #pragma config WDTPS    = PS1           // Watchdog Timer Postscale
    #pragma config FCKSM    = CSDCMD        // Clock Switching & Fail Safe Clock Monitor
    #pragma config IESO     = OFF           // Internal/External Switch-over
    #pragma config FSOSCEN  = OFF           // Secondary Oscillator Enable
    #pragma config CP       = OFF           // Code Protect
    #pragma config BWP      = OFF           // Boot Flash Write Protect
    #pragma config PWP      = OFF           // Program Flash Write Protect
    #pragma config ICESEL   = ICS_PGx1      // ICE/ICD Comm Channel Select
    #pragma config DEBUG    = OFF           // Debugger Disabled for Starter Kit
    #pragma config JTAGEN   = OFF           // No JTAG.  Need this for RB9 to work!
/*
    #define FLASH_PAGE_SIZE             1024
    #define BOOTLOADER_SIZE             0x0BEF
    #define BOOTLOADER_BASE_ADDRESS     0x9FC00000
    #define FLASH_BASE_ADDRESS          0x9D000000
    #define FLASH_END_ADDRESS           (0x9D000000+BMXPFMSZ-1)
    #define USER_APP_RESET_ADDRESS      (0x9D006000 + 0x1000)
    #define FLASH_PAGES                 (FLASH_END_ADDRESS - FLASH_BASE_ADDRESS + 1)/FLASH_PAGE_SIZE
*/
#else
    #error "Invalid part"
#endif

#include <stdio.h>
#include <stdlib.h>

#ifdef HARMONY
#include "system/devcon/sys_devcon.h"
#include "system/ports/sys_ports.h"
#include "system/int/sys_int.h" // Harmony
#else
#include <plib.h>
#endif

#include "PS2Protocol.h"
#include "RingBuffer.h"
#include "PS2Keyboard.h"
#include "KeyTranslator.h"

uint8_t keyboard_id;
uint16_t translatedData[100];
uint16_t translatedIndex = 0;

uint8_t americanKeyboard[] = {
	0x10, 0x04, 0x1C, 0x00, 0x00, 0xF0, 0x1C, 0x00,    //a A
	0x10, 0x05, 0x32, 0x00, 0x00, 0xF0, 0x32, 0x00,    //b B
	0x10, 0x06, 0x21, 0x00, 0x00, 0xF0, 0x21, 0x00,    //c C
	0x10, 0x07, 0x23, 0x00, 0x00, 0xF0, 0x23, 0x00,    //d D
	0x10, 0x08, 0x24, 0x00, 0x00, 0xF0, 0x24, 0x00,    //e E
	0x10, 0x09, 0x2B, 0x00, 0x00, 0xF0, 0x2B, 0x00,    //f F
	0x10, 0x0A, 0x34, 0x00, 0x00, 0xF0, 0x34, 0x00,    //g G
	0x10, 0x0B, 0x33, 0x00, 0x00, 0xF0, 0x33, 0x00,    //h H
	0x10, 0x0C, 0x43, 0x00, 0x00, 0xF0, 0x43, 0x00,    //i I
	0x10, 0x0D, 0x3B, 0x00, 0x00, 0xF0, 0x3B, 0x00,    //j J
	0x10, 0x0E, 0x42, 0x00, 0x00, 0xF0, 0x42, 0x00,    //k K
	0x10, 0x0F, 0x4B, 0x00, 0x00, 0xF0, 0x4B, 0x00,    //l L
	0x10, 0x10, 0x3A, 0x00, 0x00, 0xF0, 0x3A, 0x00,    //m M
	0x10, 0x11, 0x31, 0x00, 0x00, 0xF0, 0x31, 0x00,    //n N
	0x10, 0x12, 0x44, 0x00, 0x00, 0xF0, 0x44, 0x00,    //o O
	0x10, 0x13, 0x4D, 0x00, 0x00, 0xF0, 0x4D, 0x00,    //p P
	0x10, 0x14, 0x15, 0x00, 0x00, 0xF0, 0x15, 0x00,    //q Q
	0x10, 0x15, 0x2D, 0x00, 0x00, 0xF0, 0x2D, 0x00,    //r R
	0x10, 0x16, 0x1B, 0x00, 0x00, 0xF0, 0x1B, 0x00,    //s S
	0x10, 0x17, 0x2C, 0x00, 0x00, 0xF0, 0x2C, 0x00,    //t T
	0x10, 0x18, 0x3C, 0x00, 0x00, 0xF0, 0x3C, 0x00,    //u U
	0x10, 0x19, 0x2A, 0x00, 0x00, 0xF0, 0x2A, 0x00,    //v V
	0x10, 0x1A, 0x1D, 0x00, 0x00, 0xF0, 0x1D, 0x00,    //w W
	0x10, 0x1B, 0x22, 0x00, 0x00, 0xF0, 0x22, 0x00,    //x X
	0x10, 0x1C, 0x35, 0x00, 0x00, 0xF0, 0x35, 0x00,    //y Y
	0x10, 0x1D, 0x1A, 0x00, 0x00, 0xF0, 0x1A, 0x00,    //z Z
	0x10, 0x1E, 0x16, 0x00, 0x00, 0xF0, 0x16, 0x00,    //1 !
	0x10, 0x1F, 0x1E, 0x00, 0x00, 0xF0, 0x1E, 0x00,    //2 @
	0x10, 0x20, 0x26, 0x00, 0x00, 0xF0, 0x26, 0x00,    //3 #
	0x10, 0x21, 0x25, 0x00, 0x00, 0xF0, 0x25, 0x00,    //4 $
	0x10, 0x22, 0x2E, 0x00, 0x00, 0xF0, 0x2E, 0x00,    //5 %
	0x10, 0x23, 0x36, 0x00, 0x00, 0xF0, 0x36, 0x00,    //6 ^
	0x10, 0x24, 0x3D, 0x00, 0x00, 0xF0, 0x3D, 0x00,    //7 &
	0x10, 0x25, 0x3E, 0x00, 0x00, 0xF0, 0x3E, 0x00,    //8 *
	0x10, 0x26, 0x46, 0x00, 0x00, 0xF0, 0x46, 0x00,    //9 (
	0x10, 0x27, 0x45, 0x00, 0x00, 0xF0, 0x45, 0x00,    //0 )
	0x10, 0x28, 0x5A, 0x00, 0x00, 0xF0, 0x5A, 0x00,    //Return
	0x10, 0x29, 0x76, 0x00, 0x00, 0xF0, 0x76, 0x00,    //Escape
	0x10, 0x2A, 0x66, 0x00, 0x00, 0xF0, 0x66, 0x00,    //Backspace
	0x10, 0x2B, 0x0D, 0x00, 0x00, 0xF0, 0x0D, 0x00,    //Tab
	0x10, 0x2C, 0x29, 0x00, 0x00, 0xF0, 0x29, 0x00,    //Space
	0x10, 0x2D, 0x4E, 0x00, 0x00, 0xF0, 0x4E, 0x00,    //- _
	0x10, 0x2E, 0x55, 0x00, 0x00, 0xF0, 0x55, 0x00,    //= +
	0x10, 0x2F, 0x54, 0x00, 0x00, 0xF0, 0x54, 0x00,    //[ {
	0x10, 0x30, 0x5B, 0x00, 0x00, 0xF0, 0x5B, 0x00,    //] }
	0x10, 0x31, 0x5D, 0x00, 0x00, 0xF0, 0x5D, 0x00,    //\ |
	0x10, 0x33, 0x4C, 0x00, 0x00, 0xF0, 0x4C, 0x00,    //; :
	0x10, 0x34, 0x52, 0x00, 0x00, 0xF0, 0x52, 0x00,    //' "
	0x10, 0x35, 0x0E, 0x00, 0x00, 0xF0, 0x0E, 0x00,    //` ~
	0x10, 0x36, 0x41, 0x00, 0x00, 0xF0, 0x41, 0x00,    //, <
	0x10, 0x37, 0x49, 0x00, 0x00, 0xF0, 0x49, 0x00,    //. >
	0x10, 0x38, 0x4A, 0x00, 0x00, 0xF0, 0x4A, 0x00,    /// ?
	0x10, 0x39, 0x58, 0x00, 0x00, 0xF0, 0x58, 0x00,    //Caps Lock
	0x10, 0x3A, 0x05, 0x00, 0x00, 0xF0, 0x05, 0x00,    //F1
	0x10, 0x3B, 0x06, 0x00, 0x00, 0xF0, 0x06, 0x00,    //F2
	0x10, 0x3C, 0x04, 0x00, 0x00, 0xF0, 0x04, 0x00,    //F3
	0x10, 0x3D, 0x0C, 0x00, 0x00, 0xF0, 0x0C, 0x00,    //F4
	0x10, 0x3E, 0x03, 0x00, 0x00, 0xF0, 0x03, 0x00,    //F5
	0x10, 0x3F, 0x0B, 0x00, 0x00, 0xF0, 0x0B, 0x00,    //F6
	0x10, 0x40, 0x83, 0x00, 0x00, 0xF0, 0x83, 0x00,    //F7
	0x10, 0x41, 0x0A, 0x00, 0x00, 0xF0, 0x0A, 0x00,    //F8
	0x10, 0x42, 0x01, 0x00, 0x00, 0xF0, 0x01, 0x00,    //F9
	0x10, 0x43, 0x09, 0x00, 0x00, 0xF0, 0x09, 0x00,    //F10
	0x10, 0x44, 0x78, 0x00, 0x00, 0xF0, 0x78, 0x00,    //F11
	0x10, 0x45, 0x07, 0x00, 0x00, 0xF0, 0x07, 0x00,    //F12
	0x10, 0x46, 0xE0, 0x7C, 0x00, 0xE0, 0xF0, 0x7C,    //Print Screen
	0x10, 0x47, 0x7E, 0x00, 0x00, 0xF0, 0x7E, 0x00,    //Scroll Lock
	0x10, 0x49, 0xE0, 0x70, 0x00, 0xE0, 0xF0, 0x70,    //Insert
	0x10, 0x4A, 0xE0, 0x6C, 0x00, 0xE0, 0xF0, 0x6C,    //Home
	0x10, 0x4B, 0xE0, 0x7D, 0x00, 0xE0, 0xF0, 0x7D,    //Page Up
	0x10, 0x4C, 0xE0, 0x71, 0x00, 0xE0, 0xF0, 0x71,    //Delete
	0x10, 0x4D, 0xE0, 0x69, 0x00, 0xE0, 0xF0, 0x69,    //End
	0x10, 0x4E, 0xE0, 0x7A, 0x00, 0xE0, 0xF0, 0x7A,    //Page Down
	0x10, 0x4F, 0xE0, 0x74, 0x00, 0xE0, 0xF0, 0x74,    //Right Arrow
	0x10, 0x50, 0xE0, 0x6B, 0x00, 0xE0, 0xF0, 0x6B,    //Left Arrow
	0x10, 0x51, 0xE0, 0x72, 0x00, 0xE0, 0xF0, 0x72,    //Down Arrow
	0x10, 0x52, 0xE0, 0x75, 0x00, 0xE0, 0xF0, 0x75,    //Up Arrow
	0x10, 0x53, 0xE0, 0x9C, 0x00, 0xE0, 0xF0, 0x9C,    //Keypad Enter
	0x10, 0x54, 0xE0, 0xB5, 0x00, 0xE0, 0xF0, 0xB5,    //Keypad /
	0x10, 0x55, 0x77, 0x00, 0x00, 0xF0, 0x77, 0x00,    //Num Lock
	0x10, 0x56, 0x7C, 0x00, 0x00, 0xF0, 0x7C, 0x00,    //Keypad *
	0x10, 0x57, 0x7B, 0x00, 0x00, 0xF0, 0x7B, 0x00,    //Keypad -
	0x10, 0x58, 0x79, 0x00, 0x00, 0xF0, 0x79, 0x00,    //Keypad +
	0x10, 0x59, 0x69, 0x00, 0x00, 0xF0, 0x69, 0x00,    //Keypad 1 End
	0x10, 0x5A, 0x72, 0x00, 0x00, 0xF0, 0x72, 0x00,    //Keypad 2 Down
	0x10, 0x5B, 0x7A, 0x00, 0x00, 0xF0, 0x7A, 0x00,    //Keypad 3 PageDn
	0x10, 0x5C, 0x6B, 0x00, 0x00, 0xF0, 0x6B, 0x00,    //Keypad 4 Left
	0x10, 0x5D, 0x73, 0x00, 0x00, 0xF0, 0x73, 0x00,    //Keypad 5
	0x10, 0x5E, 0x74, 0x00, 0x00, 0xF0, 0x74, 0x00,    //Keypad 6 Right
	0x10, 0x5F, 0x6C, 0x00, 0x00, 0xF0, 0x6C, 0x00,    //Keypad 7 Home
	0x10, 0x60, 0x75, 0x00, 0x00, 0xF0, 0x75, 0x00,    //Keypad 8 Up
	0x10, 0x61, 0x7D, 0x00, 0x00, 0xF0, 0x7D, 0x00,    //Keypad 9 PageUp
	0x10, 0x62, 0x70, 0x00, 0x00, 0xF0, 0x70, 0x00,    //Keypad 0 Insert
	0x10, 0x63, 0x71, 0x00, 0x00, 0xF0, 0x71, 0x00,    //Keypad . Delete
	0x10, 0xE0, 0x14, 0x00, 0x00, 0xF0, 0x14, 0x00,    //Left Control
	0x10, 0xE1, 0x12, 0x00, 0x00, 0xF0, 0x12, 0x00,    //Left Shift
	0x10, 0xE2, 0x11, 0x00, 0x00, 0xF0, 0x11, 0x00,    //Left Alt
	0x10, 0xE3, 0xE0, 0x1F, 0x00, 0xE0, 0xF0, 0x1F,    //Left GUI
	0x10, 0xE4, 0xE0, 0x14, 0x00, 0xE0, 0xF0, 0x14,    //Right Control
	0x10, 0xE5, 0x59, 0x00, 0x00, 0xF0, 0x59, 0x00,    //Right Shift
	0x10, 0xE6, 0xE0, 0x11, 0x00, 0xE0, 0xF0, 0x11,    //Right Alt
	0x10, 0xE7, 0xE0, 0x27, 0x00, 0xE0, 0xF0, 0x27,    //Right GUI
};

#ifdef PS2_KEYBOARD_TEST
unsigned char keyboardData[100][3];
unsigned char dataIndex = 0;

void PS2_Keyboard_Int(unsigned char code1, unsigned char code2, unsigned char code3){
#ifdef KEY_TRANSLATE_TEST
    if (code1 < 0xe0)
        Translate(keyboard_id,code1,code2,code3);
    else
        Translate(keyboard_id,code1,code2,code3);
#else
    keyboardData[dataIndex][0] = code1;
    keyboardData[dataIndex][1] = code2;
    keyboardData[dataIndex++][2] = code3;
    if (dataIndex == 15){
        int a = 0;
    }
#endif
}
#else

#ifdef PS2_PROTOCOL_INT
void PS2_Available_Int(){
    unsigned char code;
    code = PS2_GetScanCode();   // fetch the scan code
    AddToBuffer(code);
    if (code == 0x1c){
        int a = 1;
        a++;
        PS2_Available();
    } 
}
#endif
#endif

void Translated_Key(uint16_t code){
    if (code == 0x8061){  //'a'
        int a = 1;
        a++;
    }
    translatedData[translatedIndex++] =  code;
}

void Translated_Command(uint8_t command, bool success, uint8_t data){
    if (command == PS2K_RESET){
        bool s = success;
        uint8_t d = data;
        int a = 0;
        a++;
    }
}

main()
{
    unsigned char code;
    int gotkey = 0;

#ifdef HARMONY
    // Should init clock but we are not real Harmony app.
    // SYS_Initialize ( NULL );
#else
    SYSTEMConfig( SYS_FREQ, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);
#endif

#ifdef PS2_KEYBOARD_TEST
    PS2K_Init();
#else
    PS2_Init();                  // kbd initialization
#endif

#ifdef HARMONY
    PLIB_INT_MultiVectorSelect(INT_ID_0);
    PLIB_INT_Enable(INT_ID_0);
#else
    INTEnableSystemMultiVectoredInt();
#endif

#ifndef PS2_KEYBOARD_TEST
#ifdef PS2_PROTOCOL_INT
    PS2_Callback(PS2_Available_Int);
#endif

    PS2_Send(0xff); // Reset keyboard.  Keyboard ill return 0xFA as result if success.

#else
    memset(keyboardData,0,sizeof(keyboardData));

#ifdef KEY_TRANSLATE_TEST
    // Set up the translator if it is being used.
    uint8_t codes[BYTES_PER_KEY];
    TranslatorInit();
    keyboard_id = AllocateTranslator(110);
    TranslatorCallback(keyboard_id,Translated_Key,Translated_Command);
    CreateTranlatedData(codes,0x1c,0,0,0xf0,0x1c,0);    //a
    AddConversion(keyboard_id,0x61,codes);
    CreateTranlatedData(codes,0x32,0,0,0xf0,0x32,0);    //b
    AddConversion(keyboard_id,0x62,codes);
    CreateTranlatedData(codes,0x21,0,0,0xf0,0x21,0);    //c
    AddConversion(keyboard_id,0x63,codes);
    CreateTranlatedData(codes,0x2e,0,0,0xf0,0x2e,0);    //5
    AddConversion(keyboard_id,0x35,codes);
    CreateTranlatedData(codes,0x36,0,0,0xf0,0x36,0);    //6
    AddConversion(keyboard_id,0x36,codes);
    CreateTranlatedData(codes,0xE0,0x23,0,0xE0,0xF0,0x23);  //mute
    AddConversion(keyboard_id,0x100,codes);

    keyboard_id = BeginKeyTranslationMatrix(keyboard_id, 104);
    TranslatorCallback(keyboard_id,Translated_Key,Translated_Command);
    /*
    AddKeyTranslationMatrix(0x61);
    AddKeyTranslationMatrix(0x00);
    AddKeyTranslationMatrix(0x32);
    AddKeyTranslationMatrix(0x00);
    AddKeyTranslationMatrix(0x00);
    AddKeyTranslationMatrix(0xF0);
    AddKeyTranslationMatrix(0x32);
    AddKeyTranslationMatrix(0x00);
     */
    int index;
    int size = sizeof(americanKeyboard) / 8;
    int offset;
    for (index = 0; index < size; index++){
        for (offset = 0; offset < 8; offset++){
            AddKeyTranslationMatrix(americanKeyboard[index * 8 + offset]);
        }
    }

#endif

    PS2K_Callback(PS2_Keyboard_Int);

    PS2K_ResetKeyboard();

#ifndef KEY_TRANSLATE_TEST
    PS2K_Echo();
    PS2K_SetLED(PS2K_NUM_LOCK | PS2K_CAPS_LOCK);
    PS2K_SetToDefaults();
    PS2K_DisableScanning();
    PS2K_EnableScanning();
    PS2K_Echo();
    PS2K_ResendLastByte();
    PS2K_SetScanCodeSet(PS2K_SET_2);
    PS2K_SetTypematicRateDelay(0,PS2K_DELAY_1000ms);
    PS2K_ResetKeyboard();
#endif

#endif



    while (1){
        while ( !gotkey)
        {

#ifndef PS2_PROTOCOL_INT

            if ( PS2_Available() )        // wait for the flag
            {
                code = PS2_GetScanCode();   // fetch the scan code
                AddToBuffer(code);
                if (code == 0x1c){
                    int a = 1;
                    a++;
                    PS2_Available();
                }
            }
#endif
        } 
    }
} 